package com.sinping.qh.repository.mongo.noticebook.impl;

import com.google.common.collect.Lists;
import com.sinping.qh.domain.lab.LaboratoryDomain;
import com.sinping.qh.query.base.AggregateParams;
import com.sinping.qh.repository.mongo.lab.LaboratoryRepository;
import com.sinping.qh.repository.mongo.noticebook.NoticeBookRepository;
import com.sinping.qh.service.common.CommonDbConst;
import com.sinping.qh.utils.time.DateFormatUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.*;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.stereotype.Service;
import com.sinping.qh.dto.mongo.auth.UserSessionDTO;

import java.text.ParseException;
import java.util.*;

/**
 * @author jiahuaiqing
 * @create 2018/6/28
 */
@Service
public class NoticeBookRepositoryImpl {

    @Autowired
    NoticeBookRepository noticeBookRepository;

    @Autowired
    private LaboratoryRepository laboratoryRepository;

    @Autowired
    private MongoTemplate template;

    /**
     * 查询已经下发的通知书列表（权限：所负责院系）
     *
     * @param unitIDList
     * @param clazz
     * @param targetClazz
     * @param <T>
     * @return
     */
    public <T> List<T> findPageByUniting(Map<String, Object> condition, List<String> unitIDList,List<String> labIDLists,
                                         PageRequest page,
                                         Class<?> clazz, Class<T> targetClazz) {
        List<AggregationOperation> operations = Lists.newArrayList();

        //添加权限
//        List<String> unitIDList = userSessionDto.getUnitIDList();

//        List<String> labs = userSessionDto.getLabIDList();

        for (String labId : labIDLists) {

            LaboratoryDomain laboratoryDomain =
                    laboratoryRepository.findByIdAndStatus(labId, CommonDbConst.DB_DELETE_NORMAL);
            if (laboratoryDomain != null && !unitIDList.contains(laboratoryDomain.getUnitId())) {
                unitIDList.add(laboratoryDomain.getUnitId());
            }

        }

        //排序
        if (page != null) {
            SortOperation sortOperation = new SortOperation(page.getSort());
            operations.add(sortOperation);
        }

        Criteria mainCriteria = new Criteria();
//        Set<String> units = new HashSet<>();
//        if (null != unitIDList && unitIDList.size() > 0) {
//            for (int i = 0; i < unitIDList.size(); i++) {
//                units.add(unitIDList.get(i));
//            }
//        } else {
//            units.add("");
//        }

        //按条件查询
        String receiveUnitName = (String) condition.get("notice_receive_unit_name");
        String startTime = (String) condition.get("notice_send_date_start");
        String endTime = (String) condition.get("notice_send_date_end");
        /**处理开始时间和结束时间**/
        Date newStartDate = null, newEndDate = null;
        if (null != startTime) {
            try {
                Date datestart = DateFormatUtil.pareDate("yyyy-MM-dd", startTime);
                String startDate = DateFormatUtil.formatDate("yyyy-MM-dd 00:00:00", datestart);
                newStartDate = DateFormatUtil.pareDate(DateFormatUtil.PATTERN_DEFAULT_ON_SECOND, startDate);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }

        if (null != endTime) {
            try {
                Date dateEnd = DateFormatUtil.pareDate("yyyy-MM-dd", endTime);
                String endDate = DateFormatUtil.formatDate("yyyy-MM-dd 23:59:59", dateEnd);
                newEndDate = DateFormatUtil.pareDate(DateFormatUtil.PATTERN_DEFAULT_ON_SECOND, endDate);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        /**处理开始时间和结束时间**/


        //通知书状态 0待审核  1审核退回  2审核通过  3已下发  4已完成  5已作废
        Set<String> noticeStatus = new HashSet<>();
        noticeStatus.add("3");
        noticeStatus.add("4");

        Criteria one;
        if (StringUtils.isNotBlank(receiveUnitName) && startTime == null && endTime == null) {
            one = Criteria.where("notice_receive_unit_id").in(unitIDList);

            Criteria two = Criteria.where("notice_status").in(noticeStatus);
            Criteria three = Criteria.where("notice_receive_unit_name").regex("^(.*" + receiveUnitName + ".*)$");
            mainCriteria.andOperator(one, two, three);
        } else if (!StringUtils.isNotBlank(receiveUnitName) && startTime != null && endTime != null) {

            one = Criteria.where("notice_receive_unit_id").in(unitIDList);

            Criteria two = Criteria.where("notice_status").in(noticeStatus);
            Criteria three = Criteria.where("notice_send_date").gte(newStartDate);
            Criteria four = Criteria.where("notice_send_date").lte(newEndDate);
            mainCriteria.andOperator(one, two, three, four);
        } else if (StringUtils.isNotBlank(receiveUnitName) && startTime != null && endTime != null) {
            one = Criteria.where("notice_receive_unit_id").in(unitIDList);

            Criteria two = Criteria.where("notice_status").in(noticeStatus);
            Criteria three = Criteria.where("notice_send_date").gte(newStartDate);
            Criteria four = Criteria.where("notice_send_date").lte(newEndDate);
            Criteria five = Criteria.where("notice_receive_unit_name").regex("^(.*" + receiveUnitName + ".*)$");
            mainCriteria.andOperator(one, two, three, four, five);
        } else if (StringUtils.isNotBlank(receiveUnitName) && startTime == null && endTime != null) {
            one = Criteria.where("notice_receive_unit_id").in(unitIDList);

            Criteria two = Criteria.where("notice_status").in(noticeStatus);
            Criteria four = Criteria.where("notice_send_date").lte(newEndDate);
            Criteria five = Criteria.where("notice_receive_unit_name").regex("^(.*" + receiveUnitName + ".*)$");
            mainCriteria.andOperator(one, two, four, five);
        } else if (StringUtils.isNotBlank(receiveUnitName) && startTime != null && endTime == null) {
            one = Criteria.where("notice_receive_unit_id").in(unitIDList);

            Criteria two = Criteria.where("notice_status").in(noticeStatus);
            Criteria three = Criteria.where("notice_send_date").gte(newStartDate);
            Criteria five = Criteria.where("notice_receive_unit_name").regex("^(.*" + receiveUnitName + ".*)$");
            mainCriteria.andOperator(one, two, three, five);
        } else if (!StringUtils.isNotBlank(receiveUnitName) && startTime == null && endTime != null) {

            one = Criteria.where("notice_receive_unit_id").in(unitIDList);

            Criteria two = Criteria.where("notice_status").in(noticeStatus);
            Criteria four = Criteria.where("notice_send_date").lte(newEndDate);
            mainCriteria.andOperator(one, two, four);
        } else if (!StringUtils.isNotBlank(receiveUnitName) && startTime != null && endTime == null) {
            one = Criteria.where("notice_receive_unit_id").in(unitIDList);

            Criteria two = Criteria.where("notice_status").in(noticeStatus);
            Criteria three = Criteria.where("notice_send_date").gte(newStartDate);
            mainCriteria.andOperator(one, two, three);
        } else {
            one = Criteria.where("notice_receive_unit_id").in(unitIDList);

            Criteria two = Criteria.where("notice_status").in(noticeStatus);
            mainCriteria.andOperator(one, two);
        }


        operations.add(Aggregation.match(mainCriteria));
        if (page != null) {
            SkipOperation skipOperation = new SkipOperation(page.getOffset());
            operations.add(skipOperation);
            LimitOperation limitOperation = new LimitOperation(page.getPageSize());
            operations.add(limitOperation);

        }


//        //查询隐患记录数据不为0和隐患状态未完成的检查记录
//        LookupOperation lookupOperation
//                = LookupOperation.newLookup()
//                .from("tb_hidden_danger")
//                .localField("_id")
//                .foreignField("check_id")
//                .as("hidenrecords");
//        operations.add(lookupOperation);
//
//        HashSet<String> hiddStatus = new HashSet<>();
//        hiddStatus.add("0");
//        hiddStatus.add("1");
//        hiddStatus.add("2");
//        Criteria criteria = Criteria.where("hidenrecords").ne(new HashSet<>())
//                .and("hidenrecords.hidden_danger_status").in(hiddStatus);
//        operations.add(Aggregation.match(criteria));


        Aggregation aggregation = Aggregation.newAggregation(operations);
        String table = template.getCollectionName(clazz);
        AggregationResults<T> results = template.aggregate(aggregation, table, targetClazz);
        return results.getMappedResults();
    }


    /**
     * 参考了CheckRecordServiceImpl$findPageByUniting 的分组查询
     *
     * @param hiddenDangerIds
     * @param groupParams
     * @param aggregateParams
     * @param clazz
     * @param targetClazz
     * @param <T>
     * @return
     */
    public <T> List<T> findUnitByHiddenDangerIds(List<String> hiddenDangerIds, List<String> groupParams, AggregateParams aggregateParams,
                                                 Class<?> clazz, Class<T> targetClazz) {
        List<AggregationOperation> operations = Lists.newArrayList();


        //添加权限
//        Criteria mainCriteria =new Criteria();
//        Criteria one =Criteria.where("check_unit_id").in(unitIDList);
//        Criteria two =Criteria.where("check_lab_id").in(labIDList);
//        mainCriteria.orOperator(one,two);
//        operations.add(Aggregation.match(mainCriteria));

        //查询的隐患记录必须在hiddenDangerIdsSet集合中
        Set<String> hiddenDangerIdsSet = new HashSet<>();
        for (String id :hiddenDangerIds) {
            hiddenDangerIdsSet.add(id);
        }


        Criteria userid = Criteria.where("_id").in(hiddenDangerIdsSet);
        operations.add(Aggregation.match(userid));

        // 统计参数
        GroupOperation group = Aggregation.group(groupParams.toArray(new String[groupParams.size()]));
        for (String name : aggregateParams.getFieldNames()) {
            switch (aggregateParams.getAggregateOperator(name)) {
                case avg:
                    group = group.avg(name).as(aggregateParams.getAlias(name));
                    break;
                case max:
                    group = group.max(name).as(aggregateParams.getAlias(name));
                    break;
                case min:
                    group = group.min(name).as(aggregateParams.getAlias(name));
                    break;
                case sum:
                    group = group.sum(name).as(aggregateParams.getAlias(name));
                    break;
                case last:
                    group = group.last(name).as(aggregateParams.getAlias(name));
                    break;
                case first:
                    group = group.first(name).as(aggregateParams.getAlias(name));
                    break;
                case count:
                default:
                    group = group.count().as(aggregateParams.getAlias(name));
                    break;
            }
        }
        operations.add(group);


        Aggregation aggregation = Aggregation.newAggregation(operations);
        String table = template.getCollectionName(clazz);
        AggregationResults<T> results = template.aggregate(aggregation, table, targetClazz);
        return results.getMappedResults();
    }

    public <T> List<T> findHiddenDangerRecords(List<String> hiddenDangerIds, String type, String params, Class<?> clazz, Class<T> targetClazz) {
        List<AggregationOperation> operations = Lists.newArrayList();

        Set<String> hiddenDangerIdsSet = new HashSet<>();
        for (String id:hiddenDangerIds) {
            hiddenDangerIdsSet.add(id);
        }

        Criteria mainCriteria = new Criteria();


        Criteria one = Criteria.where("_id").in(hiddenDangerIdsSet);

        if (type.equals("0")) {
            Criteria two = Criteria.where("check_lab_id").is("");
            Criteria three = Criteria.where("check_building_id").is(params);
            mainCriteria.andOperator(one, two, three);
            //mainCriteria.andOperator(one, three);
        }
        if (type.equals("1")) {
            Criteria twoLab = Criteria.where("check_lab_id").is(params);
            mainCriteria.andOperator(one, twoLab);
        }


        operations.add(Aggregation.match(mainCriteria));

//        //查询隐患记录数据不为0和隐患状态未完成的检查记录
//        LookupOperation lookupOperation
//                = LookupOperation.newLookup()
//                .from("tb_hidden_danger")
//                .localField("_id")
//                .foreignField("check_id")
//                .as("hidenrecords");
//        operations.add(lookupOperation);
//
//        HashSet<String> hiddStatus = new HashSet<>();
//        hiddStatus.add("0");
//        hiddStatus.add("1");
//        hiddStatus.add("2");
//        Criteria criteria = Criteria.where("hidenrecords").ne(new HashSet<>())
//                .and("hidenrecords.hidden_danger_status").in(hiddStatus);
//        operations.add(Aggregation.match(criteria));


        Aggregation aggregation = Aggregation.newAggregation(operations);
        String table = template.getCollectionName(clazz);
        AggregationResults<T> results = template.aggregate(aggregation, table, targetClazz);
        return results.getMappedResults();
    }

}
